#include <iostream>
#include <unistd.h>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
#include <sys/wait.h>
#include <sys/resource.h>
#include <mysql.h>
#include <cstring>
using namespace std;

#define work_dir "/home/ubuntu/quiz/"
char oj_home[] = "/home/ubuntu/quiz/";
const char query[] = "select * from jobs where isJudged < 1";
#define STD_MB 1048576
static MYSQL *conn;
static MYSQL_RES *res;
void run_client(string prbId, string uniqueId)
{

  cout << "run client" << endl;
	struct rlimit LIM;
	LIM.rlim_max = 800;
	LIM.rlim_cur = 800;
	setrlimit(RLIMIT_CPU, &LIM);        //CPU时间的最大量值（秒）

	LIM.rlim_max = 80 * STD_MB;
	LIM.rlim_cur = 80 * STD_MB;
	setrlimit(RLIMIT_FSIZE, &LIM);      //可以创建文件的最大字节长度

	LIM.rlim_max = STD_MB << 11;
	LIM.rlim_cur = STD_MB << 11;
	setrlimit(RLIMIT_AS, &LIM);         //进程总的可用存储空间的最大长度（字节）

	LIM.rlim_cur = LIM.rlim_max = 200;

  string judge_client("judge_client");
  string judge_clientFileName = work_dir + judge_client;
	if (execl(judge_clientFileName.c_str(), judge_clientFileName.c_str(), prbId.c_str() ,
			uniqueId.c_str(), oj_home, (char *) NULL) < 0)
      cerr << "error execl " << uniqueId << endl;
    exit(0);
}

int init_mysql()
{
  if (conn == NULL)
  {
    conn = mysql_init(NULL);
    const char timeout = 30;
    mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);

    if (!mysql_real_connect(conn, "127.0.0.1", "root", "960404", "quiz", 3306, 0, 0)) //连接数据库
    {
      cerr << "connect mysql error" << endl;
      return -1;
    }
  }
  return 0;
}

class job
{
private:
  string prbId;
  string uniqueId;
public:
  job (string a, string b) : prbId(a), uniqueId(b) {}
  string getPrbId()
  {
    return prbId;
  }
  string getUniqueId()
  {
    return uniqueId;
  }
};
int get_jobs(vector<job> &jobs)
{
  int num = 0;
  if (mysql_real_query(conn, query, strlen(query)))
  {
    MYSQL_ROW row;
    res = mysql_store_result(conn);
    char sqlcmd[200];
    while (row = mysql_fetch_row(res))
    {
      jobs.emplace_back(row[0], row[2]);
      sprintf(sqlcmd, "update jobs set isJudged = '1' where uniqueId = \"%s\"", row[2]);
      mysql_query(conn, sqlcmd);
      ++num;
    }
  }
  return num;
}
int main()
{
  if (init_mysql() < 0)
    return -1;
  vector<job> jobs;
  while (1)
  {
    if (get_jobs(jobs))
    {
	  //获取作业
      for (auto c : jobs)
      {
        cout << c.getUniqueId() << endl;
        pid_t pid;
        if ((pid = fork()) == 0)
        {
          pid_t p;
          if ((p = fork()) == 0)  //fork两次第一个子进程在fork之后一成为父进程就退出，讲第二个子进程交个init进程管理，避免成为僵尸进程
            run_client(c.getPrbId(), c.getUniqueId());
          else if (p > 0)
          {
            exit(0);
          }
        }
        else if (pid > 0)
          waitpid(pid, NULL, 0);
      }
      jobs.clear();
      continue;
    }
    else
    {
	  //再次进入获取作业
      sleep(1);
      continue;
    }
  }
}
